<!DOCTYPE html>
<html lang="zh">
<head>
  <meta charset="UTF-8">
  <title>TTS 语音合成测试</title>
  <style>
    body { font-family: sans-serif; padding: 20px; }
    textarea { width: 100%; height: 80px; margin-bottom: 10px; }
    button { padding: 8px 16px; }
  </style>
</head>
<body>
  <h2>实时语音合成 (PCM 播放)</h2>
  <textarea id="text" placeholder="请输入要合成的文本"></textarea><br>
  <button onclick="sendText()">开始合成</button>
  <p id="status">状态：未连接</p>

  <script>
    let ws;
    let audioContext = new (window.AudioContext || window.webkitAudioContext)({ sampleRate: 16000 });
    let currentSource = null;
    let playing = false;
    let connected = false;

    function initWebSocket(callback) {
      ws = new WebSocket("ws://127.0.0.1:8000/ws/tts");
      ws.binaryType = "arraybuffer";

      ws.onopen = () => {
        connected = true;
        document.getElementById("status").innerText = "状态：已连接";
        if (callback) callback();
      };

      ws.onmessage = (event) => {
        if (typeof event.data === "string" && event.data === "[END]") {
          document.getElementById("status").innerText = "状态：播放完成";
          playing = false;
          return;
        }

        if (event.data instanceof ArrayBuffer) {
          playPCM(event.data);
        }
      };

      ws.onerror = (e) => {
        console.error("WebSocket 错误:", e);
        document.getElementById("status").innerText = "状态：连接失败";
        connected = false;
      };

      ws.onclose = () => {
        console.log("WebSocket 已关闭");
        connected = false;
      };
    }

    function sendText() {
      const text = document.getElementById("text").value.trim();
      if (!text) return alert("请输入文本");

      // 停止上一段播放
      if (currentSource) {
        currentSource.stop();
        currentSource = null;
      }

      playing = true;
      document.getElementById("status").innerText = "状态：正在发送并播放中...";

      if (!connected || ws.readyState !== 1) {
        initWebSocket(() => {
          ws.send(text);
        });
      } else {
        ws.send(text);
      }
    }

    function playPCM(arrayBuffer) {
      const buffer = audioContext.createBuffer(1, arrayBuffer.byteLength / 2, 16000);
      const channelData = buffer.getChannelData(0);
      const dataView = new DataView(arrayBuffer);

      for (let i = 0; i < arrayBuffer.byteLength / 2; i++) {
        let sample = dataView.getInt16(i * 2, true); // 小端序
        channelData[i] = sample / 32768.0; // 归一化 [-1, 1]
      }

      const source = audioContext.createBufferSource();
      source.buffer = buffer;
      source.connect(audioContext.destination);
      source.start();

      currentSource = source;
    }
  </script>
</body>
</html>
